Setup

Clean directory and load packages

Objective

The objective of this notebooks is to update the extraction list for our collaborative PWS Pink Salmon whole genome re-sequencing (WGR) project with the Christie Lab at Purdue University. The goal of this notebook is 2-fold:

  1. Reconcile and update the final list of fish in P076 (there was an error where PSPRIN14 replacement fish were not updated in iStrategy Wells table)
  2. Join in all paired data from AHRP Pedigree collections (length, otolith mark id, location, parentage info?), and clarify that all PopStructure collections are upstream, not intertidal

Background

This project is using leftover Pink Salmon Disaster 2016 funds to try to address questions about potential genetic mechanisms causing reduced RRS. This project is broken into two main questions:

The study design for this extraction list comes from:

V:\Documents\5_Coastwide\Multispecies\AHRP\Pink Salmon Disaster Funding\Round2\Objective 11 PWS WGR\Sample Units.xlsx
Sheet 2

Sample Units

Screenshot of sample design

Screenshot of sample design

Using “output/PWS Pink Salmon WGR Extraction List.xlsx” and “output/extraction_selection.xlsx” to hand-pick most extractions

Reconcile P076 Fish

Read in the original and revised P076 Wells tables from LOKI iStrategy (internal ADF&G GCL database).

(wells_original <- readr::read_csv(file = "../data/P076 for Sequencing_Wells_original_bad.csv"))
Rows: 1039 Columns: 6── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Silly Code, Well, Tissue Type
dbl (3): Lab Project ID, Plate ID, Fish
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(wells_revised <- readr::read_csv(file = "../data/P076 for Sequencing_Wells_revised_good.csv"))
Rows: 1039 Columns: 6── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Silly Code, Well, Tissue Type
dbl (3): Lab Project ID, Plate ID, Fish
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

How many different fish?

Fish that are the 12 fish with missing tissues that we did not end up using.

dplyr::anti_join(x = dplyr::select(.data = wells_original, `Silly Code`, `Fish`), y = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`))
Joining, by = c("Silly Code", "Fish")

Replacement 12 fish that got extracted and sequenced.

dplyr::anti_join(x = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`), y = dplyr::select(.data = wells_original, `Silly Code`, `Fish`))
Joining, by = c("Silly Code", "Fish")

How about well locations?

We know that we had 12 fish replacements, but we need to check if these replacements changed the DNA plate map.

What is wrong?

This is the original fish and well location info. These are wrong.

dplyr::anti_join(x = wells_original, y = wells_revised)
Joining, by = c("Lab Project ID", "Plate ID", "Silly Code", "Fish", "Well", "Tissue Type")

What is correct now?

These is the revised fish and well location info. This is the correct fish and well location data that should be used moving forward.

dplyr::anti_join(x = wells_revised, y = wells_original)
Joining, by = c("Lab Project ID", "Plate ID", "Silly Code", "Fish", "Well", "Tissue Type")

Conclusion

There were 12 fish that were originally selected for DNA extraction that had missing tissues. Those 12 fish were replaced and then prior to DNA extraction, the DNA plate map was re-sorted by Fish ID, so it resulted in 32 fish from collection PSRIN14 getting shifted into different wells. No other collections were affected, everything else is as it should be.

Update extraction_selection.xlsx individuals tab

How many fish per silly?

Read in all PSPRIN14 extractions

extraction_selection_PSPRIN14_PSPRIN15 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_PSPRIN15.csv") %>% 
  dplyr::select(-dwp_barcode)
Rows: 72 Columns: 9── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (6): silly_source, silly, dwp_barcode, tissue_type, sex, otolith_mark_present
dbl  (2): fish_id, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
extraction_selection_PSPRIN14_v2 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_v2.csv")
Rows: 12 Columns: 9── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): silly_source, silly, tissue_type, sex, otolith_mark_present
dbl  (3): fish_id, dwp_barcode, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
extraction_selection_PSPRIN14_v3 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_v3.csv")
Rows: 8 Columns: 9── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): silly_source, silly, tissue_type, sex, otolith_mark_present
dbl  (3): fish_id, dwp_barcode, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(
  extraction_PSRPIN14 <-
    dplyr::bind_rows(
      extraction_selection_PSPRIN14_PSPRIN15,
      extraction_selection_PSPRIN14_v2,
      extraction_selection_PSPRIN14_v3
    )
)

Join up with wells_revised

(
  wells_revised %>%
    dplyr::filter(`Silly Code` == "PSPRIN14") %>%
    dplyr::rename(silly = "Silly Code",
                  fish_id = "Fish") %>%
    dplyr::select(silly, fish_id) %>%
    dplyr::left_join(extraction_PSRPIN14, by = c("silly", "fish_id")) %>%
    dplyr::select(silly, fish_id, sex, otolith_mark_present, sample_date) %>%
    dplyr::mutate(
      sex = dplyr::case_when(sex == "M" ~ "male",
                             sex == "F" ~ "female"),
      origin = dplyr::case_when(
        otolith_mark_present == "NO" ~ "natural",
        otolith_mark_present == "YES" ~ "hatchery",
        TRUE ~ otolith_mark_present
      )
    ) %>%
    dplyr::select(silly, fish_id, sex, origin, sample_date) %>%
    readr::write_csv(file = "../output/extraction_PSPRIN14_revised.csv")
)

Paired data

Read

Location

Read in all riverdist output.

(
  stream_specimens_riverdist_all_streams_2013_2020 <-
    readr::read_csv(file = "../data/stream_specimens_riverdist_all_streams_2013_2020.csv")
)
Rows: 235693 Columns: 15── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): Sample, ADFGStreamCode, StreamName, SpawningState
dbl (8): riverdist_seg, riverdist_vert, riverdist_snapdist, Latitude, Longitude, mouthdist, hitide, dist2tide
lgl (3): PreSpawn, PartialSpawner, PreyedUpon
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Reformat to get intertidal vs. upstream.

(
  location_tidal <-
    stream_specimens_riverdist_all_streams_2013_2020 %>%
    dplyr::rename(sample = Sample,
                  distance_tide = dist2tide) %>%
    dplyr::mutate(
      intertidal = dplyr::case_when(
        distance_tide <= 0 ~ "Intertidal",
        distance_tide > 0 ~ "Upstream",
        is.na(distance_tide) ~  NA_character_
      )  # create intertidal
    ) %>%
    dplyr::select(sample, intertidal)
)

Length + Otolith

erb_2017 <-
  readr::read_csv(file = "../data/Erb 2017 AHRP Salmon Biological Data 20220321_151027.csv")
Rows: 14955 Columns: 22── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_ID,...
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_M...
lgl  (5): TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_ARRAY_TYPE, DETERMI...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
stockdale_2015_2016_hogan_2015_2016 <-
  readr::read_csv(file = "../data/Stockdale 2015-2016 Hogan 2015-2016 Spring 2014-2015 AHRP Salmon Biological Data 20220322_115608.csv")
Rows: 80100 Columns: 22── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_ID,...
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_M...
lgl  (5): TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_ARRAY_TYPE, DETERMI...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
spring_2014_2015 <-
  readr::read_csv(file = "../data/Spring 2014-2015 AHRP Salmon Biological Data 20220322_122538.csv")
Warning: One or more parsing issues, see `problems()` for detailsRows: 25240 Columns: 22── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (8): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_STA...
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_M...
lgl  (6): OTOLITH_MARK_ID, TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_AR...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(oceanak_og <- dplyr::bind_rows(erb_2017,
                               stockdale_2015_2016_hogan_2015_2016,
                               spring_2014_2015)
)

Reformat

(
  oceanak <- oceanak_og %>%
    dplyr::filter(TISSUE_TYPE == "Heart-bulbus arteriosus") %>%
    dplyr::rename(
      silly = SILLY_CODE,
      fish_id = FISH_ID,
      tissue_type = TISSUE_TYPE,
      dwp_barcode = DNA_TRAY_CODE,
      dwp_well = DNA_TRAY_WELL_CODE,
      sample_date = SAMPLE_DATE,
      sex = SEX,
      length_mm_meh = LENGTH_MM,
      otolith_mark_present = OTOLITH_MARK_PRESENT,
      otolith_mark_id = OTOLITH_MARK_ID
    ) %>%
    dplyr::mutate(
      sample_date = lubridate::ymd(sample_date),
      hatchery = dplyr::case_when(
        !is.na(otolith_mark_id) ~ stringr::str_sub(
          string = otolith_mark_id,
          start = 1,
          end = 3
        ),
        TRUE ~ otolith_mark_id
      ),
      origin = dplyr::case_when(
        otolith_mark_present == "NO" ~ "natural",
        otolith_mark_present == "YES" ~ "hatchery"
      ),
      sex = dplyr::case_when(
        sex == "M" ~ "male",
        sex == "F" ~ "female",
        sex == "U" ~ "unknown",
        TRUE ~ sex
      )
    ) %>%
    tidyr::unite(
      col = "silly_source",
      c(silly, fish_id),
      sep = "_",
      remove = FALSE
    ) %>%
    tidyr::unite(
      col = "sample",
      c(dwp_barcode, dwp_well),
      sep = "_",
      remove = FALSE
    ) %>%
    dplyr::select(
      silly_source,
      sample,
      silly,
      fish_id,
      dwp_barcode,
      dwp_well,
      sample_date,
      sex,
      length_mm_meh,
      origin,
      otolith_mark_present,
      otolith_mark_id,
      hatchery
    )
)

Join

Join in location data to the everything else from the data warehouse.

(paired_data <- oceanak %>%
   dplyr::left_join(y = location_tidal, by = "sample"))

Now join this all in with the wells_revised

wells_revised %>% 
  tidyr::unite(
      col = "silly_source",
      c("Silly Code", "Fish"),
      sep = "_",
      remove = FALSE
    ) %>%
  dplyr::left_join(y = paired_data, by = "silly_source") %>% 
  dplyr::filter(!is.na(sample))

Double check to make sure this is how many fish we should have…

Whew, we did it

Read in extraction_selection.xlsx tab individuals

(individuals <- readxl::read_xlsx(path = "../output/extraction_selection.xlsx", sheet = "individuals"))

We are going to replace this tab with a join between wells_revised, the existing individuals tab, and our new paired data

(
  individuals_new <- wells_revised %>%
    dplyr::select(-`Lab Project ID`) %>%
    dplyr::rename(
      dna_plate_id = "Plate ID",
      silly = "Silly Code",
      fish_id = "Fish",
      dna_plate_well = "Well",
      tissue_type = "Tissue Type"
    ) %>%
    dplyr::select(dna_plate_id,
                  dna_plate_well,
                  silly,
                  fish_id,
                  tissue_type) %>%
    dplyr::left_join(y = individuals, by = c("silly", "fish_id")) %>%
    dplyr::left_join(
      y = select(.data = paired_data,-c(sex, origin, sample_date)),
      by = c("silly", "fish_id")
    )
)

Great, write all of this out, paste into extraction_selection_revised_20221014.xlsx as the new individuals tab, annotate the columns, send to Will.

readr::write_csv(x = individuals_new, file = "../output/extraction_selection_revised_20221014.csv")

End…time for a beer

Re-Visited 11/15/22

PSPRIN14, DNA plate 63218 strikes again!

Background

After our last go around re-visiting this, William Hemstrom (Mark Christie’s new post-doc from UC Davis) noticed on 11/3/22 that one sample from plate 63218 was incorrect. The issue was well A7 vs. B7. He is seeing B7 as a NTC, whereas in our update we had A7 as the NTC.

Kristen looked at the DNA quant data from the BioTek plate reader and she saw that we had DNA in A7 and C7, but B7 was consistent with an NTC (e-mail on 11/4/22).

Heather and Erin Dooley looked at the plate map again and resolved the error on 11/14/22, B7 is now back to an NTC (jives with Will’s data and Kristen’s quant data).

I just need to double check that only A7 and B7 changed, then send Will the update!

Reconcile P076 Fish - AGAIN

Read in the original and revised P076 Wells tables from LOKI iStrategy (internal ADF&G GCL database).

(wells_original <- readr::read_csv(file = "../data/P076 for Sequencing_Wells_original_bad.csv"))
Rows: 1039 Columns: 6── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Silly Code, Well, Tissue Type
dbl (3): Lab Project ID, Plate ID, Fish
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(wells_revised <- readr::read_csv(file = "../data/P076 for Sequencing_Wells_revised_good.csv"))
Rows: 1039 Columns: 6── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Silly Code, Well, Tissue Type
dbl (3): Lab Project ID, Plate ID, Fish
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(wells_revised_v2 <- readr::read_csv(file = "../data/P076 for Sequencing_Wells_revised_v2_better.csv"))
Rows: 1039 Columns: 6── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Silly Code, Well, Tissue Type
dbl (3): Lab Project ID, Plate ID, Fish
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

How many different fish?

Are there any differences in the fish?

dplyr::anti_join(
  x = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`),
  y = dplyr::select(.data = wells_revised_v2, `Silly Code`, `Fish`)
)
Joining, by = c("Silly Code", "Fish")

Yes, PSPRIN14_176 no longer exists (which is as it should be)

Are there any differences in the fish?

dplyr::anti_join(
  x = dplyr::select(.data = wells_revised_v2, `Silly Code`, `Fish`),
  y = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`)
)
Joining, by = c("Silly Code", "Fish")

And PSPRIN14_175 does exist (which is also as it should be)

How many different wells?

Are there any differences in the wells?

dplyr::anti_join(
  x = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`, `Plate ID`, `Well`),
  y = dplyr::select(.data = wells_revised_v2, `Silly Code`, `Fish`, `Plate ID`, `Well`)
)
Joining, by = c("Silly Code", "Fish", "Plate ID", "Well")

Are there any differences in the wells?

dplyr::anti_join(
  x = dplyr::select(.data = wells_revised_v2, `Silly Code`, `Fish`, `Plate ID`, `Well`),
  y = dplyr::select(.data = wells_revised, `Silly Code`, `Fish`, `Plate ID`, `Well`)
)
Joining, by = c("Silly Code", "Fish", "Plate ID", "Well")

Conclusion

Okay, cool, all is well now (pun intended). Heather and Erin accidently messed up the plate map for 63218 when they were fixing things last go around. They have caught that error and update the extraction manager, collection manager, and iStrategy for P076. PSPRIN14_176 no longer exists, 63218_B7 is an NTC, and PSPRIN14_175 is in 63218_A7. No other collections were affected, everything else is as it should be.

Update extraction_selection.xlsx individuals tab

How many fish per silly?

wells_revised_v2 %>% 
  dplyr::count(`Silly Code`)

Read in all PSPRIN14 extractions

extraction_selection_PSPRIN14_PSPRIN15 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_PSPRIN15.csv") %>% 
  dplyr::select(-dwp_barcode)
Rows: 72 Columns: 9── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (6): silly_source, silly, dwp_barcode, tissue_type, sex, otolith_mark_present
dbl  (2): fish_id, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
extraction_selection_PSPRIN14_v2 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_v2.csv")
Rows: 12 Columns: 9── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): silly_source, silly, tissue_type, sex, otolith_mark_present
dbl  (3): fish_id, dwp_barcode, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
extraction_selection_PSPRIN14_v3 <-
  readr::read_csv(file = "../output/extraction_selection_PSPRIN14_v3.csv")
Rows: 8 Columns: 9── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): silly_source, silly, tissue_type, sex, otolith_mark_present
dbl  (3): fish_id, dwp_barcode, dwp_well
date (1): sample_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(
  extraction_PSRPIN14 <-
    dplyr::bind_rows(
      extraction_selection_PSPRIN14_PSPRIN15,
      extraction_selection_PSPRIN14_v2,
      extraction_selection_PSPRIN14_v3
    )
)

Join up with wells_revised_v2

(
  wells_revised_v2 %>%
    dplyr::filter(`Silly Code` == "PSPRIN14") %>%
    dplyr::rename(silly = "Silly Code",
                  fish_id = "Fish") %>%
    dplyr::select(silly, fish_id) %>%
    dplyr::left_join(extraction_PSRPIN14, by = c("silly", "fish_id")) %>%
    dplyr::select(silly, fish_id, sex, otolith_mark_present, sample_date) %>%
    dplyr::mutate(
      sex = dplyr::case_when(sex == "M" ~ "male",
                             sex == "F" ~ "female"),
      origin = dplyr::case_when(
        otolith_mark_present == "NO" ~ "natural",
        otolith_mark_present == "YES" ~ "hatchery",
        TRUE ~ otolith_mark_present
      )
    ) %>%
    dplyr::select(silly, fish_id, sex, origin, sample_date) %>%
    readr::write_csv(file = "../output/extraction_PSPRIN14_revised_v2.csv")
)

Paired data

Read

Location

Read in all riverdist output.

(
  stream_specimens_riverdist_all_streams_2013_2020 <-
    readr::read_csv(file = "../data/stream_specimens_riverdist_all_streams_2013_2020.csv")
)
Rows: 235693 Columns: 15── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): Sample, ADFGStreamCode, StreamName, SpawningState
dbl (8): riverdist_seg, riverdist_vert, riverdist_snapdist, Latitude, Longitude, mouthdist, hitide, dist2tide
lgl (3): PreSpawn, PartialSpawner, PreyedUpon
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Reformat to get intertidal vs. upstream.

(
  location_tidal <-
    stream_specimens_riverdist_all_streams_2013_2020 %>%
    dplyr::rename(sample = Sample,
                  distance_tide = dist2tide) %>%
    dplyr::mutate(
      intertidal = dplyr::case_when(
        distance_tide <= 0 ~ "Intertidal",
        distance_tide > 0 ~ "Upstream",
        is.na(distance_tide) ~  NA_character_
      )  # create intertidal
    ) %>%
    dplyr::select(sample, intertidal)
)

Length + Otolith

erb_2017 <-
  readr::read_csv(file = "../data/Erb 2017 AHRP Salmon Biological Data 20220321_151027.csv")
Rows: 14955 Columns: 22── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_ID, OTOLITH_MARK...
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_MORE_THAN_ONE_...
lgl  (5): TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_ARRAY_TYPE, DETERMINATION_COLLEC...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
stockdale_2015_2016_hogan_2015_2016 <-
  readr::read_csv(file = "../data/Stockdale 2015-2016 Hogan 2015-2016 Spring 2014-2015 AHRP Salmon Biological Data 20220322_115608.csv")
Rows: 80100 Columns: 22── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_ID, OTOLITH_MARK...
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_MORE_THAN_ONE_...
lgl  (5): TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_ARRAY_TYPE, DETERMINATION_COLLEC...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
spring_2014_2015 <-
  readr::read_csv(file = "../data/Spring 2014-2015 AHRP Salmon Biological Data 20220322_122538.csv")
Warning: One or more parsing issues, see `problems()` for detailsRows: 25240 Columns: 22── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (8): SILLY_CODE, SEX, TISSUE_TYPE, DNA_TRAY_CODE, LOCATION_CODE, SAMPLE_ID, OTOLITH_MARK_PRESENT, OTOLITH_MARK_STATUS_CODE
dbl  (7): COLLECTION_ID, FISH_ID, LENGTH_MM, DNA_TRAY_WELL_CODE, SAMPLE_YEAR, IS_MISSING_PAIRED_DATA_EXISTS, WELL_HAS_MORE_THAN_ONE_...
lgl  (6): OTOLITH_MARK_ID, TARGET_DNA_TRAY_CODE, TARGET_DNA_TRAY_WELL_POS, TARGET_CONTAINER_ARRAY_TYPE_ID, CONTAINER_ARRAY_TYPE, DET...
dttm (1): SAMPLE_DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
(oceanak_og <- dplyr::bind_rows(erb_2017,
                               stockdale_2015_2016_hogan_2015_2016,
                               spring_2014_2015)
)

Confirm the absence of length data for PSPRIN14_175

Reformat

(
  oceanak <- oceanak_og %>%
    dplyr::filter(TISSUE_TYPE == "Heart-bulbus arteriosus") %>%
    dplyr::rename(
      silly = SILLY_CODE,
      fish_id = FISH_ID,
      tissue_type = TISSUE_TYPE,
      dwp_barcode = DNA_TRAY_CODE,
      dwp_well = DNA_TRAY_WELL_CODE,
      sample_date = SAMPLE_DATE,
      sex = SEX,
      length_mm_meh = LENGTH_MM,
      otolith_mark_present = OTOLITH_MARK_PRESENT,
      otolith_mark_id = OTOLITH_MARK_ID
    ) %>%
    dplyr::mutate(
      sample_date = lubridate::ymd(sample_date),
      hatchery = dplyr::case_when(
        !is.na(otolith_mark_id) ~ stringr::str_sub(
          string = otolith_mark_id,
          start = 1,
          end = 3
        ),
        TRUE ~ otolith_mark_id
      ),
      origin = dplyr::case_when(
        otolith_mark_present == "NO" ~ "natural",
        otolith_mark_present == "YES" ~ "hatchery"
      ),
      sex = dplyr::case_when(
        sex == "M" ~ "male",
        sex == "F" ~ "female",
        sex == "U" ~ "unknown",
        TRUE ~ sex
      )
    ) %>%
    tidyr::unite(
      col = "silly_source",
      c(silly, fish_id),
      sep = "_",
      remove = FALSE
    ) %>%
    tidyr::unite(
      col = "sample",
      c(dwp_barcode, dwp_well),
      sep = "_",
      remove = FALSE
    ) %>%
    dplyr::select(
      silly_source,
      sample,
      silly,
      fish_id,
      dwp_barcode,
      dwp_well,
      sample_date,
      sex,
      length_mm_meh,
      origin,
      otolith_mark_present,
      otolith_mark_id,
      hatchery
    )
)

Join

Join in location data to the everything else from the data warehouse.

(paired_data <- oceanak %>%
   dplyr::left_join(y = location_tidal, by = "sample"))

Now join this all in with the wells_revised_v2

wells_revised_v2 %>% 
  tidyr::unite(
      col = "silly_source",
      c("Silly Code", "Fish"),
      sep = "_",
      remove = FALSE
    ) %>%
  dplyr::left_join(y = paired_data, by = "silly_source") %>% 
  dplyr::filter(!is.na(sample))

Double check to make sure this is how many fish we should have…

wells_revised_v2 %>% 
  dplyr::filter(`Silly Code` %in% c("PERB17", "PHOGAN15", "PHOGAN16", "PSPRIN14", "PSPRIN15", "PSTOCK15", "PSTOCK16")) %>% 
  dplyr::count(`Silly Code`)

Whew, we did it

Read in extraction_selection.xlsx tab individuals

(
  individuals <-
    readxl::read_xlsx(path = "../output/extraction_selection_revised_20221014.xlsx", sheet = "individuals") %>%
    dplyr::select(silly, fish_id, sex, origin, date, comment) %>% 
    dplyr::mutate(date = lubridate::as_date(date))
)
Warning:  86 failed to parse.

Stopped here, need to fix this 11/15/22! paired_data is NOT joining, for whatever esoteric reason.

We are going to replace this tab with a join between wells_revised, the existing individuals tab, and our new paired data

(
  individuals_new <- wells_revised_v2 %>%
    dplyr::select(-`Lab Project ID`) %>%
    dplyr::rename(
      dna_plate_id = "Plate ID",
      silly = "Silly Code",
      fish_id = "Fish",
      dna_plate_well = "Well",
      tissue_type = "Tissue Type"
    ) %>%
    dplyr::select(dna_plate_id,
                  dna_plate_well,
                  silly,
                  fish_id,
                  tissue_type) %>%
    tidyr::unite(
      col = "silly_source",
      c("silly", "fish_id"),
      sep = "_",
      remove = FALSE
    ) %>%
    dplyr::left_join(y = individuals, by = c("silly", "fish_id")) %>%
    dplyr::left_join(
      y = paired_data,
      by = "silly_source",
      suffix = c("_indiv", "_paired")
    )
)

Double check our hommie in 63218_A7

individuals_new %>% 
  dplyr::filter(dna_plate_id == 63218)

Great, write all of this out, paste into extraction_selection_revised_20221115.xlsx as the new individuals tab, annotate the columns, send to Will.

readr::write_csv(x = individuals_new, file = "../output/extraction_selection_revised_20221115.csv")

End…time for a beer

LS0tDQp0aXRsZTogIkluZGl2aWR1YWwgUGFpcmVkIERhdGEgZm9yIEV4dHJhY3Rpb24gTGlzdCBmb3IgUFdTIFBpbmsgU2FsbW9uIFdHUiINCnN1YnRpdGxlOiAiRml4IFBTUFJJTjE0IEZpc2ggTWl4dXAgKyBKb2luIEFsbCBQYWlyZWQgRGF0YSINCmF1dGhvcjogIkt5bGUgU2hlZGQiDQpkYXRlOiAiMTQgT2N0b2JlciAyMDIyIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICB0b2M6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KIyBTZXR1cA0KDQpDbGVhbiBkaXJlY3RvcnkgYW5kIGxvYWQgcGFja2FnZXMNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Kcm0obGlzdD1scygpKQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQoNCmlmKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIik7IGxpYnJhcnkocGFjbWFuKQ0KDQpwYWNtYW46OnBfbG9hZCgNCiAgdGlkeXZlcnNlLA0KICBsdWJyaWRhdGUsDQogIERUDQopDQoNCiMgc291cmNlKCJ+Ly4uL1IvRnVuY3Rpb25zLkdDTC5SIikgICMgZGV2ZWxvcCBicmFuY2ghISENCmBgYA0KDQojIE9iamVjdGl2ZQ0KDQpUaGUgb2JqZWN0aXZlIG9mIHRoaXMgbm90ZWJvb2tzIGlzIHRvIHVwZGF0ZSB0aGUgZXh0cmFjdGlvbiBsaXN0IGZvciBvdXIgY29sbGFib3JhdGl2ZSBQV1MgUGluayBTYWxtb24gd2hvbGUgZ2Vub21lIHJlLXNlcXVlbmNpbmcgKFdHUikgcHJvamVjdCB3aXRoIHRoZSBDaHJpc3RpZSBMYWIgYXQgIFB1cmR1ZSBVbml2ZXJzaXR5LiBUaGUgZ29hbCBvZiB0aGlzIG5vdGVib29rIGlzIDItZm9sZDoNCg0KICAxKSBSZWNvbmNpbGUgYW5kIHVwZGF0ZSB0aGUgZmluYWwgbGlzdCBvZiBmaXNoIGluIFAwNzYgKHRoZXJlIHdhcyBhbiBlcnJvciB3aGVyZSBQU1BSSU4xNCByZXBsYWNlbWVudCBmaXNoIHdlcmUgbm90IHVwZGF0ZWQgaW4gaVN0cmF0ZWd5IFdlbGxzIHRhYmxlKSAgDQogIDIpIEpvaW4gaW4gKmFsbCogcGFpcmVkIGRhdGEgZnJvbSBBSFJQIFBlZGlncmVlIGNvbGxlY3Rpb25zIChsZW5ndGgsIG90b2xpdGggbWFyayBpZCwgbG9jYXRpb24sIHBhcmVudGFnZSBpbmZvPyksIGFuZCBjbGFyaWZ5IHRoYXQgYWxsIFBvcFN0cnVjdHVyZSBjb2xsZWN0aW9ucyBhcmUgdXBzdHJlYW0sIG5vdCBpbnRlcnRpZGFsDQoNCiMgQmFja2dyb3VuZA0KDQpUaGlzIHByb2plY3QgaXMgdXNpbmcgbGVmdG92ZXIgUGluayBTYWxtb24gRGlzYXN0ZXIgMjAxNiBmdW5kcyB0byB0cnkgdG8gYWRkcmVzcyBxdWVzdGlvbnMgYWJvdXQgcG90ZW50aWFsIGdlbmV0aWMgbWVjaGFuaXNtcyBjYXVzaW5nIHJlZHVjZWQgUlJTLiBUaGlzIHByb2plY3QgaXMgYnJva2VuIGludG8gdHdvIG1haW4gcXVlc3Rpb25zOiAgDQoNCiAgKiBBIC0gZ2Vub21pYyBldmlkZW5jZSBmb3IgZG9tZXN0aWNhdGlvbiBzZWxlY3Rpb24gb3ZlciB0aW1lIChjb21wYXJpbmcgaGlzdG9yaWNhbCB2cy4gY29udGVtcG9yYXJ5IHZzLiBicm9vZCBzb3VyY2UgY29sbGVjdGlvbnMpICANCiAgKiBCIC0gZ2Vub21pYyBkaWZmZXJlbmNlcyBiZXR3ZWVuIGhhdGNoZXJ5IHN0cmF5cyB2cy4gbmF0dXJhbC1vcmlnaW4gaG9taW5nIGluZGl2aWR1YWxzDQoNClRoZSBzdHVkeSBkZXNpZ24gZm9yIHRoaXMgZXh0cmFjdGlvbiBsaXN0IGNvbWVzIGZyb206DQoNCiAgICBWOlxEb2N1bWVudHNcNV9Db2FzdHdpZGVcTXVsdGlzcGVjaWVzXEFIUlBcUGluayBTYWxtb24gRGlzYXN0ZXIgRnVuZGluZ1xSb3VuZDJcT2JqZWN0aXZlIDExIFBXUyBXR1JcU2FtcGxlIFVuaXRzLnhsc3gNCiAgICBTaGVldCAyDQoNCiAgKiAyOSBzYW1wbGUgdW5pdHMgIA0KICAqIDM2IGluZGl2aWR1YWxzIHBlciBzYW1wbGVzIHVuaXQgIA0KICAqIDEsMDQ0IHRvdGFsIGluZGl2aWR1YWxzICANCg0KIyMgU2FtcGxlIFVuaXRzDQoNCiFbU2NyZWVuc2hvdCBvZiBzYW1wbGUgZGVzaWduXSguLi9kYXRhL3NhbXBsZV91bml0cy5QTkcpDQoNClVzaW5nICJvdXRwdXQvUFdTIFBpbmsgU2FsbW9uIFdHUiBFeHRyYWN0aW9uIExpc3QueGxzeCIgYW5kICJvdXRwdXQvZXh0cmFjdGlvbl9zZWxlY3Rpb24ueGxzeCIgdG8gaGFuZC1waWNrIG1vc3QgZXh0cmFjdGlvbnMNCg0KIyBSZWNvbmNpbGUgUDA3NiBGaXNoDQoNClJlYWQgaW4gdGhlIG9yaWdpbmFsIGFuZCByZXZpc2VkIFAwNzYgV2VsbHMgdGFibGVzIGZyb20gKkxPS0kqIGlTdHJhdGVneSAoaW50ZXJuYWwgQURGJkcgR0NMIGRhdGFiYXNlKS4NCmBgYHtyfQ0KKHdlbGxzX29yaWdpbmFsIDwtIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL2RhdGEvUDA3NiBmb3IgU2VxdWVuY2luZ19XZWxsc19vcmlnaW5hbF9iYWQuY3N2IikpDQood2VsbHNfcmV2aXNlZCA8LSByZWFkcjo6cmVhZF9jc3YoZmlsZSA9ICIuLi9kYXRhL1AwNzYgZm9yIFNlcXVlbmNpbmdfV2VsbHNfcmV2aXNlZF9nb29kLmNzdiIpKQ0KYGBgDQoNCiMjIEhvdyBtYW55IGRpZmZlcmVudCBmaXNoPw0KDQpGaXNoIHRoYXQgYXJlIHRoZSAxMiBmaXNoIHdpdGggbWlzc2luZyB0aXNzdWVzIHRoYXQgd2UgZGlkICoqbm90KiogZW5kIHVwIHVzaW5nLg0KYGBge3J9DQpkcGx5cjo6YW50aV9qb2luKA0KICB4ID0gZHBseXI6OnNlbGVjdCguZGF0YSA9IHdlbGxzX29yaWdpbmFsLCBgU2lsbHkgQ29kZWAsIGBGaXNoYCksDQogIHkgPSBkcGx5cjo6c2VsZWN0KC5kYXRhID0gd2VsbHNfcmV2aXNlZCwgYFNpbGx5IENvZGVgLCBgRmlzaGApDQopDQpgYGANCg0KUmVwbGFjZW1lbnQgMTIgZmlzaCB0aGF0IGdvdCBleHRyYWN0ZWQgYW5kIHNlcXVlbmNlZC4NCmBgYHtyfQ0KZHBseXI6OmFudGlfam9pbigNCiAgeCA9IGRwbHlyOjpzZWxlY3QoLmRhdGEgPSB3ZWxsc19yZXZpc2VkLCBgU2lsbHkgQ29kZWAsIGBGaXNoYCksDQogIHkgPSBkcGx5cjo6c2VsZWN0KC5kYXRhID0gd2VsbHNfb3JpZ2luYWwsIGBTaWxseSBDb2RlYCwgYEZpc2hgKQ0KKQ0KYGBgDQoNCiMjIEhvdyBhYm91dCB3ZWxsIGxvY2F0aW9ucz8NCg0KV2Uga25vdyB0aGF0IHdlIGhhZCAxMiBmaXNoIHJlcGxhY2VtZW50cywgYnV0IHdlIG5lZWQgdG8gY2hlY2sgaWYgdGhlc2UgcmVwbGFjZW1lbnRzIGNoYW5nZWQgdGhlIEROQSBwbGF0ZSBtYXAuDQoNCiMjIyBXaGF0IGlzIHdyb25nPw0KDQpUaGlzIGlzIHRoZSAqKm9yaWdpbmFsKiogZmlzaCBhbmQgd2VsbCBsb2NhdGlvbiBpbmZvLiBUaGVzZSBhcmUgKip3cm9uZyoqLg0KYGBge3J9DQpkcGx5cjo6YW50aV9qb2luKHggPSB3ZWxsc19vcmlnaW5hbCwgeSA9IHdlbGxzX3JldmlzZWQpDQpgYGANCg0KIyMjIFdoYXQgaXMgY29ycmVjdCBub3c/DQoNClRoZXNlIGlzIHRoZSAqKnJldmlzZWQqKiBmaXNoIGFuZCB3ZWxsIGxvY2F0aW9uIGluZm8uIFRoaXMgaXMgdGhlICoqY29ycmVjdCoqIGZpc2ggYW5kIHdlbGwgbG9jYXRpb24gZGF0YSB0aGF0IHNob3VsZCBiZSB1c2VkIG1vdmluZyBmb3J3YXJkLg0KYGBge3J9DQpkcGx5cjo6YW50aV9qb2luKHggPSB3ZWxsc19yZXZpc2VkLCB5ID0gd2VsbHNfb3JpZ2luYWwpDQpgYGANCg0KIyMgQ29uY2x1c2lvbg0KDQpUaGVyZSB3ZXJlIDEyIGZpc2ggdGhhdCB3ZXJlIG9yaWdpbmFsbHkgc2VsZWN0ZWQgZm9yIEROQSBleHRyYWN0aW9uIHRoYXQgaGFkIG1pc3NpbmcgdGlzc3Vlcy4gVGhvc2UgMTIgZmlzaCB3ZXJlIHJlcGxhY2VkIGFuZCB0aGVuIHByaW9yIHRvIEROQSBleHRyYWN0aW9uLCB0aGUgRE5BIHBsYXRlIG1hcCB3YXMgcmUtc29ydGVkIGJ5IEZpc2ggSUQsIHNvIGl0IHJlc3VsdGVkIGluIDMyIGZpc2ggZnJvbSBjb2xsZWN0aW9uIFBTUklOMTQgZ2V0dGluZyBzaGlmdGVkIGludG8gZGlmZmVyZW50IHdlbGxzLiBObyBvdGhlciBjb2xsZWN0aW9ucyB3ZXJlIGFmZmVjdGVkLCBldmVyeXRoaW5nIGVsc2UgaXMgYXMgaXQgc2hvdWxkIGJlLg0KDQojIyBVcGRhdGUgYGV4dHJhY3Rpb25fc2VsZWN0aW9uLnhsc3hgIGluZGl2aWR1YWxzIHRhYg0KDQpIb3cgbWFueSBmaXNoIHBlciBzaWxseT8NCmBgYHtyfQ0Kd2VsbHNfcmV2aXNlZCAlPiUgDQogIGRwbHlyOjpjb3VudChgU2lsbHkgQ29kZWApDQpgYGANCg0KUmVhZCBpbiBhbGwgUFNQUklOMTQgZXh0cmFjdGlvbnMNCmBgYHtyfQ0KZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfUFNQUklOMTUgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vb3V0cHV0L2V4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X1BTUFJJTjE1LmNzdiIpICU+JSANCiAgZHBseXI6OnNlbGVjdCgtZHdwX2JhcmNvZGUpDQpleHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92MiA8LQ0KICByZWFkcjo6cmVhZF9jc3YoZmlsZSA9ICIuLi9vdXRwdXQvZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfdjIuY3N2IikNCmV4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X3YzIDwtDQogIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL291dHB1dC9leHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92My5jc3YiKQ0KDQooDQogIGV4dHJhY3Rpb25fUFNSUElOMTQgPC0NCiAgICBkcGx5cjo6YmluZF9yb3dzKA0KICAgICAgZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfUFNQUklOMTUsDQogICAgICBleHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92MiwNCiAgICAgIGV4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X3YzDQogICAgKQ0KKQ0KYGBgDQoNCkpvaW4gdXAgd2l0aCBgd2VsbHNfcmV2aXNlZGANCmBgYHtyfQ0KKA0KICB3ZWxsc19yZXZpc2VkICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoYFNpbGx5IENvZGVgID09ICJQU1BSSU4xNCIpICU+JQ0KICAgIGRwbHlyOjpyZW5hbWUoc2lsbHkgPSAiU2lsbHkgQ29kZSIsDQogICAgICAgICAgICAgICAgICBmaXNoX2lkID0gIkZpc2giKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKGV4dHJhY3Rpb25fUFNSUElOMTQsIGJ5ID0gYygic2lsbHkiLCAiZmlzaF9pZCIpKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkLCBzZXgsIG90b2xpdGhfbWFya19wcmVzZW50LCBzYW1wbGVfZGF0ZSkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHNleCA9IGRwbHlyOjpjYXNlX3doZW4oc2V4ID09ICJNIiB+ICJtYWxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V4ID09ICJGIiB+ICJmZW1hbGUiKSwNCiAgICAgIG9yaWdpbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJOTyIgfiAibmF0dXJhbCIsDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJZRVMiIH4gImhhdGNoZXJ5IiwNCiAgICAgICAgVFJVRSB+IG90b2xpdGhfbWFya19wcmVzZW50DQogICAgICApDQogICAgKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkLCBzZXgsIG9yaWdpbiwgc2FtcGxlX2RhdGUpICU+JQ0KICAgIHJlYWRyOjp3cml0ZV9jc3YoZmlsZSA9ICIuLi9vdXRwdXQvZXh0cmFjdGlvbl9QU1BSSU4xNF9yZXZpc2VkLmNzdiIpDQopDQpgYGANCg0KIyBQYWlyZWQgZGF0YQ0KDQojIyBSZWFkDQoNCiMjIyBMb2NhdGlvbg0KDQpSZWFkIGluIGFsbCBgcml2ZXJkaXN0YCBvdXRwdXQuDQpgYGB7cn0NCigNCiAgc3RyZWFtX3NwZWNpbWVuc19yaXZlcmRpc3RfYWxsX3N0cmVhbXNfMjAxM18yMDIwIDwtDQogICAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9zdHJlYW1fc3BlY2ltZW5zX3JpdmVyZGlzdF9hbGxfc3RyZWFtc18yMDEzXzIwMjAuY3N2IikNCikNCmBgYA0KDQpSZWZvcm1hdCB0byBnZXQgaW50ZXJ0aWRhbCB2cy4gdXBzdHJlYW0uDQpgYGB7cn0NCigNCiAgbG9jYXRpb25fdGlkYWwgPC0NCiAgICBzdHJlYW1fc3BlY2ltZW5zX3JpdmVyZGlzdF9hbGxfc3RyZWFtc18yMDEzXzIwMjAgJT4lDQogICAgZHBseXI6OnJlbmFtZShzYW1wbGUgPSBTYW1wbGUsDQogICAgICAgICAgICAgICAgICBkaXN0YW5jZV90aWRlID0gZGlzdDJ0aWRlKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgaW50ZXJ0aWRhbCA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIGRpc3RhbmNlX3RpZGUgPD0gMCB+ICJJbnRlcnRpZGFsIiwNCiAgICAgICAgZGlzdGFuY2VfdGlkZSA+IDAgfiAiVXBzdHJlYW0iLA0KICAgICAgICBpcy5uYShkaXN0YW5jZV90aWRlKSB+ICBOQV9jaGFyYWN0ZXJfDQogICAgICApICAjIGNyZWF0ZSBpbnRlcnRpZGFsDQogICAgKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNhbXBsZSwgaW50ZXJ0aWRhbCkNCikNCmBgYA0KDQojIyMgTGVuZ3RoICsgT3RvbGl0aA0KDQpgYGB7cn0NCmVyYl8yMDE3IDwtDQogIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL2RhdGEvRXJiIDIwMTcgQUhSUCBTYWxtb24gQmlvbG9naWNhbCBEYXRhIDIwMjIwMzIxXzE1MTAyNy5jc3YiKQ0Kc3RvY2tkYWxlXzIwMTVfMjAxNl9ob2dhbl8yMDE1XzIwMTYgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9TdG9ja2RhbGUgMjAxNS0yMDE2IEhvZ2FuIDIwMTUtMjAxNiBTcHJpbmcgMjAxNC0yMDE1IEFIUlAgU2FsbW9uIEJpb2xvZ2ljYWwgRGF0YSAyMDIyMDMyMl8xMTU2MDguY3N2IikNCnNwcmluZ18yMDE0XzIwMTUgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9TcHJpbmcgMjAxNC0yMDE1IEFIUlAgU2FsbW9uIEJpb2xvZ2ljYWwgRGF0YSAyMDIyMDMyMl8xMjI1MzguY3N2IikNCg0KKG9jZWFuYWtfb2cgPC0gZHBseXI6OmJpbmRfcm93cyhlcmJfMjAxNywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9ja2RhbGVfMjAxNV8yMDE2X2hvZ2FuXzIwMTVfMjAxNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbmdfMjAxNF8yMDE1KQ0KKQ0KYGBgDQoNClJlZm9ybWF0DQpgYGB7cn0NCigNCiAgb2NlYW5hayA8LSBvY2VhbmFrX29nICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoVElTU1VFX1RZUEUgPT0gIkhlYXJ0LWJ1bGJ1cyBhcnRlcmlvc3VzIikgJT4lDQogICAgZHBseXI6OnJlbmFtZSgNCiAgICAgIHNpbGx5ID0gU0lMTFlfQ09ERSwNCiAgICAgIGZpc2hfaWQgPSBGSVNIX0lELA0KICAgICAgdGlzc3VlX3R5cGUgPSBUSVNTVUVfVFlQRSwNCiAgICAgIGR3cF9iYXJjb2RlID0gRE5BX1RSQVlfQ09ERSwNCiAgICAgIGR3cF93ZWxsID0gRE5BX1RSQVlfV0VMTF9DT0RFLA0KICAgICAgc2FtcGxlX2RhdGUgPSBTQU1QTEVfREFURSwNCiAgICAgIHNleCA9IFNFWCwNCiAgICAgIGxlbmd0aF9tbV9tZWggPSBMRU5HVEhfTU0sDQogICAgICBvdG9saXRoX21hcmtfcHJlc2VudCA9IE9UT0xJVEhfTUFSS19QUkVTRU5ULA0KICAgICAgb3RvbGl0aF9tYXJrX2lkID0gT1RPTElUSF9NQVJLX0lEDQogICAgKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgc2FtcGxlX2RhdGUgPSBsdWJyaWRhdGU6OnltZChzYW1wbGVfZGF0ZSksDQogICAgICBoYXRjaGVyeSA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgICFpcy5uYShvdG9saXRoX21hcmtfaWQpIH4gc3RyaW5ncjo6c3RyX3N1YigNCiAgICAgICAgICBzdHJpbmcgPSBvdG9saXRoX21hcmtfaWQsDQogICAgICAgICAgc3RhcnQgPSAxLA0KICAgICAgICAgIGVuZCA9IDMNCiAgICAgICAgKSwNCiAgICAgICAgVFJVRSB+IG90b2xpdGhfbWFya19pZA0KICAgICAgKSwNCiAgICAgIG9yaWdpbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJOTyIgfiAibmF0dXJhbCIsDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJZRVMiIH4gImhhdGNoZXJ5Ig0KICAgICAgKSwNCiAgICAgIHNleCA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIHNleCA9PSAiTSIgfiAibWFsZSIsDQogICAgICAgIHNleCA9PSAiRiIgfiAiZmVtYWxlIiwNCiAgICAgICAgc2V4ID09ICJVIiB+ICJ1bmtub3duIiwNCiAgICAgICAgVFJVRSB+IHNleA0KICAgICAgKQ0KICAgICkgJT4lDQogICAgdGlkeXI6OnVuaXRlKA0KICAgICAgY29sID0gInNpbGx5X3NvdXJjZSIsDQogICAgICBjKHNpbGx5LCBmaXNoX2lkKSwNCiAgICAgIHNlcCA9ICJfIiwNCiAgICAgIHJlbW92ZSA9IEZBTFNFDQogICAgKSAlPiUNCiAgICB0aWR5cjo6dW5pdGUoDQogICAgICBjb2wgPSAic2FtcGxlIiwNCiAgICAgIGMoZHdwX2JhcmNvZGUsIGR3cF93ZWxsKSwNCiAgICAgIHNlcCA9ICJfIiwNCiAgICAgIHJlbW92ZSA9IEZBTFNFDQogICAgKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KA0KICAgICAgc2lsbHlfc291cmNlLA0KICAgICAgc2FtcGxlLA0KICAgICAgc2lsbHksDQogICAgICBmaXNoX2lkLA0KICAgICAgZHdwX2JhcmNvZGUsDQogICAgICBkd3Bfd2VsbCwNCiAgICAgIHNhbXBsZV9kYXRlLA0KICAgICAgc2V4LA0KICAgICAgbGVuZ3RoX21tX21laCwNCiAgICAgIG9yaWdpbiwNCiAgICAgIG90b2xpdGhfbWFya19wcmVzZW50LA0KICAgICAgb3RvbGl0aF9tYXJrX2lkLA0KICAgICAgaGF0Y2hlcnkNCiAgICApDQopDQpgYGANCg0KIyMgSm9pbg0KDQpKb2luIGluIGxvY2F0aW9uIGRhdGEgdG8gdGhlIGV2ZXJ5dGhpbmcgZWxzZSBmcm9tIHRoZSBkYXRhIHdhcmVob3VzZS4NCmBgYHtyfQ0KKHBhaXJlZF9kYXRhIDwtIG9jZWFuYWsgJT4lDQogICBkcGx5cjo6bGVmdF9qb2luKHkgPSBsb2NhdGlvbl90aWRhbCwgYnkgPSAic2FtcGxlIikpDQpgYGANCg0KTm93IGpvaW4gdGhpcyBhbGwgaW4gd2l0aCB0aGUgYHdlbGxzX3JldmlzZWRgDQpgYGB7cn0NCndlbGxzX3JldmlzZWQgJT4lIA0KICB0aWR5cjo6dW5pdGUoDQogICAgICBjb2wgPSAic2lsbHlfc291cmNlIiwNCiAgICAgIGMoIlNpbGx5IENvZGUiLCAiRmlzaCIpLA0KICAgICAgc2VwID0gIl8iLA0KICAgICAgcmVtb3ZlID0gRkFMU0UNCiAgICApICU+JQ0KICBkcGx5cjo6bGVmdF9qb2luKHkgPSBwYWlyZWRfZGF0YSwgYnkgPSAic2lsbHlfc291cmNlIikgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShzYW1wbGUpKQ0KYGBgDQoNCkRvdWJsZSBjaGVjayB0byBtYWtlIHN1cmUgdGhpcyBpcyBob3cgbWFueSBmaXNoIHdlIHNob3VsZCBoYXZlLi4uDQpgYGB7cn0NCndlbGxzX3JldmlzZWQgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKGBTaWxseSBDb2RlYCAlaW4lIGMoIlBFUkIxNyIsICJQSE9HQU4xNSIsICJQSE9HQU4xNiIsICJQU1BSSU4xNCIsICJQU1BSSU4xNSIsICJQU1RPQ0sxNSIsICJQU1RPQ0sxNiIpKQ0KICBkcGx5cjo6Y291bnQoYFNpbGx5IENvZGVgKQ0KYGBgDQoNCldoZXcsIHdlIGRpZCBpdA0KDQojIFJlYWQgaW4gYGV4dHJhY3Rpb25fc2VsZWN0aW9uLnhsc3hgIHRhYiBpbmRpdmlkdWFscw0KDQpgYGB7cn0NCihpbmRpdmlkdWFscyA8LSByZWFkeGw6OnJlYWRfeGxzeChwYXRoID0gIi4uL291dHB1dC9leHRyYWN0aW9uX3NlbGVjdGlvbi54bHN4Iiwgc2hlZXQgPSAiaW5kaXZpZHVhbHMiKSkNCmBgYA0KDQpXZSBhcmUgZ29pbmcgdG8gcmVwbGFjZSB0aGlzIHRhYiB3aXRoIGEgam9pbiBiZXR3ZWVuIGB3ZWxsc19yZXZpc2VkYCwgdGhlIGV4aXN0aW5nIGBpbmRpdmlkdWFsc2AgdGFiLCBhbmQgb3VyIG5ldyBgcGFpcmVkIGRhdGFgDQpgYGB7cn0NCigNCiAgaW5kaXZpZHVhbHNfbmV3IDwtIHdlbGxzX3JldmlzZWQgJT4lDQogICAgZHBseXI6OnNlbGVjdCgtYExhYiBQcm9qZWN0IElEYCkgJT4lDQogICAgZHBseXI6OnJlbmFtZSgNCiAgICAgIGRuYV9wbGF0ZV9pZCA9ICJQbGF0ZSBJRCIsDQogICAgICBzaWxseSA9ICJTaWxseSBDb2RlIiwNCiAgICAgIGZpc2hfaWQgPSAiRmlzaCIsDQogICAgICBkbmFfcGxhdGVfd2VsbCA9ICJXZWxsIiwNCiAgICAgIHRpc3N1ZV90eXBlID0gIlRpc3N1ZSBUeXBlIg0KICAgICkgJT4lDQogICAgZHBseXI6OnNlbGVjdChkbmFfcGxhdGVfaWQsDQogICAgICAgICAgICAgICAgICBkbmFfcGxhdGVfd2VsbCwNCiAgICAgICAgICAgICAgICAgIHNpbGx5LA0KICAgICAgICAgICAgICAgICAgZmlzaF9pZCwNCiAgICAgICAgICAgICAgICAgIHRpc3N1ZV90eXBlKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKHkgPSBpbmRpdmlkdWFscywgYnkgPSBjKCJzaWxseSIsICJmaXNoX2lkIikpICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4oDQogICAgICB5ID0gc2VsZWN0KC5kYXRhID0gcGFpcmVkX2RhdGEsLWMoc2V4LCBvcmlnaW4sIHNhbXBsZV9kYXRlKSksDQogICAgICBieSA9IGMoInNpbGx5IiwgImZpc2hfaWQiKQ0KICAgICkNCikNCmBgYA0KR3JlYXQsIHdyaXRlIGFsbCBvZiB0aGlzIG91dCwgcGFzdGUgaW50byBgZXh0cmFjdGlvbl9zZWxlY3Rpb25fcmV2aXNlZF8yMDIyMTAxNC54bHN4YCBhcyB0aGUgbmV3IGBpbmRpdmlkdWFscyB0YWJgLCBhbm5vdGF0ZSB0aGUgY29sdW1ucywgc2VuZCB0byBXaWxsLg0KYGBge3J9DQpyZWFkcjo6d3JpdGVfY3N2KHggPSBpbmRpdmlkdWFsc19uZXcsIGZpbGUgPSAiLi4vb3V0cHV0L2V4dHJhY3Rpb25fc2VsZWN0aW9uX3JldmlzZWRfMjAyMjEwMTQuY3N2IikNCmBgYA0KDQpFbmQuLi50aW1lIGZvciBhIGJlZXINCg0KIyBSZS1WaXNpdGVkIDExLzE1LzIyDQoNClBTUFJJTjE0LCBETkEgcGxhdGUgNjMyMTggc3RyaWtlcyBhZ2FpbiENCg0KIyMgQmFja2dyb3VuZA0KDQpBZnRlciBvdXIgbGFzdCBnbyBhcm91bmQgcmUtdmlzaXRpbmcgdGhpcywgV2lsbGlhbSBIZW1zdHJvbSAoTWFyayBDaHJpc3RpZSdzIG5ldyBwb3N0LWRvYyBmcm9tIFVDIERhdmlzKSBub3RpY2VkIG9uIDExLzMvMjIgdGhhdCBvbmUgc2FtcGxlIGZyb20gcGxhdGUgNjMyMTggd2FzIGluY29ycmVjdC4gVGhlIGlzc3VlIHdhcyB3ZWxsIEE3IHZzLiBCNy4gSGUgaXMgc2VlaW5nIEI3IGFzIGEgTlRDLCB3aGVyZWFzIGluIG91ciAqdXBkYXRlKiB3ZSBoYWQgQTcgYXMgdGhlIE5UQy4NCg0KS3Jpc3RlbiBsb29rZWQgYXQgdGhlIEROQSBxdWFudCBkYXRhIGZyb20gdGhlIEJpb1RlayBwbGF0ZSByZWFkZXIgYW5kIHNoZSBzYXcgdGhhdCB3ZSBoYWQgRE5BIGluIEE3IGFuZCBDNywgYnV0IEI3IHdhcyBjb25zaXN0ZW50IHdpdGggYW4gTlRDIChlLW1haWwgb24gMTEvNC8yMikuDQoNCkhlYXRoZXIgYW5kIEVyaW4gRG9vbGV5IGxvb2tlZCBhdCB0aGUgcGxhdGUgbWFwIGFnYWluIGFuZCByZXNvbHZlZCB0aGUgZXJyb3Igb24gMTEvMTQvMjIsIEI3IGlzIG5vdyBiYWNrIHRvIGFuIE5UQyAoaml2ZXMgd2l0aCBXaWxsJ3MgZGF0YSBhbmQgS3Jpc3RlbidzIHF1YW50IGRhdGEpLg0KDQpJIGp1c3QgbmVlZCB0byBkb3VibGUgY2hlY2sgdGhhdCBvbmx5IEE3IGFuZCBCNyBjaGFuZ2VkLCB0aGVuIHNlbmQgV2lsbCB0aGUgdXBkYXRlIQ0KDQojIyBSZWNvbmNpbGUgUDA3NiBGaXNoIC0gQUdBSU4NCg0KUmVhZCBpbiB0aGUgb3JpZ2luYWwgYW5kIHJldmlzZWQgUDA3NiBXZWxscyB0YWJsZXMgZnJvbSAqTE9LSSogaVN0cmF0ZWd5IChpbnRlcm5hbCBBREYmRyBHQ0wgZGF0YWJhc2UpLg0KYGBge3J9DQood2VsbHNfb3JpZ2luYWwgPC0gcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9QMDc2IGZvciBTZXF1ZW5jaW5nX1dlbGxzX29yaWdpbmFsX2JhZC5jc3YiKSkNCih3ZWxsc19yZXZpc2VkIDwtIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL2RhdGEvUDA3NiBmb3IgU2VxdWVuY2luZ19XZWxsc19yZXZpc2VkX2dvb2QuY3N2IikpDQood2VsbHNfcmV2aXNlZF92MiA8LSByZWFkcjo6cmVhZF9jc3YoZmlsZSA9ICIuLi9kYXRhL1AwNzYgZm9yIFNlcXVlbmNpbmdfV2VsbHNfcmV2aXNlZF92Ml9iZXR0ZXIuY3N2IikpDQpgYGANCg0KIyMgSG93IG1hbnkgZGlmZmVyZW50IGZpc2g/DQoNCkFyZSB0aGVyZSBhbnkgZGlmZmVyZW5jZXMgaW4gdGhlIGZpc2g/DQpgYGB7cn0NCmRwbHlyOjphbnRpX2pvaW4oDQogIHggPSBkcGx5cjo6c2VsZWN0KC5kYXRhID0gd2VsbHNfcmV2aXNlZCwgYFNpbGx5IENvZGVgLCBgRmlzaGApLA0KICB5ID0gZHBseXI6OnNlbGVjdCguZGF0YSA9IHdlbGxzX3JldmlzZWRfdjIsIGBTaWxseSBDb2RlYCwgYEZpc2hgKQ0KKQ0KYGBgDQoNClllcywgUFNQUklOMTRfMTc2IG5vIGxvbmdlciBleGlzdHMgKHdoaWNoIGlzIGFzIGl0IHNob3VsZCBiZSkNCg0KQXJlIHRoZXJlIGFueSBkaWZmZXJlbmNlcyBpbiB0aGUgZmlzaD8NCmBgYHtyfQ0KZHBseXI6OmFudGlfam9pbigNCiAgeCA9IGRwbHlyOjpzZWxlY3QoLmRhdGEgPSB3ZWxsc19yZXZpc2VkX3YyLCBgU2lsbHkgQ29kZWAsIGBGaXNoYCksDQogIHkgPSBkcGx5cjo6c2VsZWN0KC5kYXRhID0gd2VsbHNfcmV2aXNlZCwgYFNpbGx5IENvZGVgLCBgRmlzaGApDQopDQpgYGANCg0KQW5kIFBTUFJJTjE0XzE3NSBkb2VzIGV4aXN0ICh3aGljaCBpcyBhbHNvIGFzIGl0IHNob3VsZCBiZSkNCg0KIyMgSG93IG1hbnkgZGlmZmVyZW50IHdlbGxzPw0KDQpBcmUgdGhlcmUgYW55IGRpZmZlcmVuY2VzIGluIHRoZSB3ZWxscz8NCmBgYHtyfQ0KZHBseXI6OmFudGlfam9pbigNCiAgeCA9IGRwbHlyOjpzZWxlY3QoLmRhdGEgPSB3ZWxsc19yZXZpc2VkLCBgU2lsbHkgQ29kZWAsIGBGaXNoYCwgYFBsYXRlIElEYCwgYFdlbGxgKSwNCiAgeSA9IGRwbHlyOjpzZWxlY3QoLmRhdGEgPSB3ZWxsc19yZXZpc2VkX3YyLCBgU2lsbHkgQ29kZWAsIGBGaXNoYCwgYFBsYXRlIElEYCwgYFdlbGxgKQ0KKQ0KYGBgDQoNCkFyZSB0aGVyZSBhbnkgZGlmZmVyZW5jZXMgaW4gdGhlIHdlbGxzPw0KYGBge3J9DQpkcGx5cjo6YW50aV9qb2luKA0KICB4ID0gZHBseXI6OnNlbGVjdCguZGF0YSA9IHdlbGxzX3JldmlzZWRfdjIsIGBTaWxseSBDb2RlYCwgYEZpc2hgLCBgUGxhdGUgSURgLCBgV2VsbGApLA0KICB5ID0gZHBseXI6OnNlbGVjdCguZGF0YSA9IHdlbGxzX3JldmlzZWQsIGBTaWxseSBDb2RlYCwgYEZpc2hgLCBgUGxhdGUgSURgLCBgV2VsbGApDQopDQpgYGANCg0KIyMgQ29uY2x1c2lvbg0KDQpPa2F5LCBjb29sLCBhbGwgaXMgd2VsbCBub3cgKHB1biBpbnRlbmRlZCkuIEhlYXRoZXIgYW5kIEVyaW4gYWNjaWRlbnRseSBtZXNzZWQgdXAgdGhlIHBsYXRlIG1hcCBmb3IgNjMyMTggd2hlbiB0aGV5IHdlcmUgZml4aW5nIHRoaW5ncyBsYXN0IGdvIGFyb3VuZC4gVGhleSBoYXZlIGNhdWdodCB0aGF0IGVycm9yIGFuZCB1cGRhdGUgdGhlIGV4dHJhY3Rpb24gbWFuYWdlciwgY29sbGVjdGlvbiBtYW5hZ2VyLCBhbmQgaVN0cmF0ZWd5IGZvciBQMDc2LiBQU1BSSU4xNF8xNzYgbm8gbG9uZ2VyIGV4aXN0cywgNjMyMThfQjcgaXMgYW4gTlRDLCBhbmQgUFNQUklOMTRfMTc1IGlzIGluIDYzMjE4X0E3LiBObyBvdGhlciBjb2xsZWN0aW9ucyB3ZXJlIGFmZmVjdGVkLCBldmVyeXRoaW5nIGVsc2UgaXMgYXMgaXQgc2hvdWxkIGJlLg0KDQojIyBVcGRhdGUgYGV4dHJhY3Rpb25fc2VsZWN0aW9uLnhsc3hgIGluZGl2aWR1YWxzIHRhYg0KDQpIb3cgbWFueSBmaXNoIHBlciBzaWxseT8NCmBgYHtyfQ0Kd2VsbHNfcmV2aXNlZF92MiAlPiUgDQogIGRwbHlyOjpjb3VudChgU2lsbHkgQ29kZWApDQpgYGANCg0KUmVhZCBpbiBhbGwgUFNQUklOMTQgZXh0cmFjdGlvbnMNCmBgYHtyfQ0KZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfUFNQUklOMTUgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vb3V0cHV0L2V4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X1BTUFJJTjE1LmNzdiIpICU+JSANCiAgZHBseXI6OnNlbGVjdCgtZHdwX2JhcmNvZGUpDQpleHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92MiA8LQ0KICByZWFkcjo6cmVhZF9jc3YoZmlsZSA9ICIuLi9vdXRwdXQvZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfdjIuY3N2IikNCmV4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X3YzIDwtDQogIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL291dHB1dC9leHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92My5jc3YiKQ0KDQooDQogIGV4dHJhY3Rpb25fUFNSUElOMTQgPC0NCiAgICBkcGx5cjo6YmluZF9yb3dzKA0KICAgICAgZXh0cmFjdGlvbl9zZWxlY3Rpb25fUFNQUklOMTRfUFNQUklOMTUsDQogICAgICBleHRyYWN0aW9uX3NlbGVjdGlvbl9QU1BSSU4xNF92MiwNCiAgICAgIGV4dHJhY3Rpb25fc2VsZWN0aW9uX1BTUFJJTjE0X3YzDQogICAgKQ0KKQ0KYGBgDQoNCkpvaW4gdXAgd2l0aCBgd2VsbHNfcmV2aXNlZF92MmANCmBgYHtyfQ0KKA0KICB3ZWxsc19yZXZpc2VkX3YyICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoYFNpbGx5IENvZGVgID09ICJQU1BSSU4xNCIpICU+JQ0KICAgIGRwbHlyOjpyZW5hbWUoc2lsbHkgPSAiU2lsbHkgQ29kZSIsDQogICAgICAgICAgICAgICAgICBmaXNoX2lkID0gIkZpc2giKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKGV4dHJhY3Rpb25fUFNSUElOMTQsIGJ5ID0gYygic2lsbHkiLCAiZmlzaF9pZCIpKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkLCBzZXgsIG90b2xpdGhfbWFya19wcmVzZW50LCBzYW1wbGVfZGF0ZSkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHNleCA9IGRwbHlyOjpjYXNlX3doZW4oc2V4ID09ICJNIiB+ICJtYWxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V4ID09ICJGIiB+ICJmZW1hbGUiKSwNCiAgICAgIG9yaWdpbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJOTyIgfiAibmF0dXJhbCIsDQogICAgICAgIG90b2xpdGhfbWFya19wcmVzZW50ID09ICJZRVMiIH4gImhhdGNoZXJ5IiwNCiAgICAgICAgVFJVRSB+IG90b2xpdGhfbWFya19wcmVzZW50DQogICAgICApDQogICAgKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNpbGx5LCBmaXNoX2lkLCBzZXgsIG9yaWdpbiwgc2FtcGxlX2RhdGUpICU+JQ0KICAgIHJlYWRyOjp3cml0ZV9jc3YoZmlsZSA9ICIuLi9vdXRwdXQvZXh0cmFjdGlvbl9QU1BSSU4xNF9yZXZpc2VkX3YyLmNzdiIpDQopDQpgYGANCg0KIyBQYWlyZWQgZGF0YQ0KDQojIyBSZWFkDQoNCiMjIyBMb2NhdGlvbg0KDQpSZWFkIGluIGFsbCBgcml2ZXJkaXN0YCBvdXRwdXQuDQpgYGB7cn0NCigNCiAgc3RyZWFtX3NwZWNpbWVuc19yaXZlcmRpc3RfYWxsX3N0cmVhbXNfMjAxM18yMDIwIDwtDQogICAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9zdHJlYW1fc3BlY2ltZW5zX3JpdmVyZGlzdF9hbGxfc3RyZWFtc18yMDEzXzIwMjAuY3N2IikNCikNCmBgYA0KDQpSZWZvcm1hdCB0byBnZXQgaW50ZXJ0aWRhbCB2cy4gdXBzdHJlYW0uDQpgYGB7cn0NCigNCiAgbG9jYXRpb25fdGlkYWwgPC0NCiAgICBzdHJlYW1fc3BlY2ltZW5zX3JpdmVyZGlzdF9hbGxfc3RyZWFtc18yMDEzXzIwMjAgJT4lDQogICAgZHBseXI6OnJlbmFtZShzYW1wbGUgPSBTYW1wbGUsDQogICAgICAgICAgICAgICAgICBkaXN0YW5jZV90aWRlID0gZGlzdDJ0aWRlKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgaW50ZXJ0aWRhbCA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIGRpc3RhbmNlX3RpZGUgPD0gMCB+ICJJbnRlcnRpZGFsIiwNCiAgICAgICAgZGlzdGFuY2VfdGlkZSA+IDAgfiAiVXBzdHJlYW0iLA0KICAgICAgICBpcy5uYShkaXN0YW5jZV90aWRlKSB+ICBOQV9jaGFyYWN0ZXJfDQogICAgICApICAjIGNyZWF0ZSBpbnRlcnRpZGFsDQogICAgKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHNhbXBsZSwgaW50ZXJ0aWRhbCkNCikNCmBgYA0KDQojIyMgTGVuZ3RoICsgT3RvbGl0aA0KDQpgYGB7cn0NCmVyYl8yMDE3IDwtDQogIHJlYWRyOjpyZWFkX2NzdihmaWxlID0gIi4uL2RhdGEvRXJiIDIwMTcgQUhSUCBTYWxtb24gQmlvbG9naWNhbCBEYXRhIDIwMjIwMzIxXzE1MTAyNy5jc3YiKQ0Kc3RvY2tkYWxlXzIwMTVfMjAxNl9ob2dhbl8yMDE1XzIwMTYgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9TdG9ja2RhbGUgMjAxNS0yMDE2IEhvZ2FuIDIwMTUtMjAxNiBTcHJpbmcgMjAxNC0yMDE1IEFIUlAgU2FsbW9uIEJpb2xvZ2ljYWwgRGF0YSAyMDIyMDMyMl8xMTU2MDguY3N2IikNCnNwcmluZ18yMDE0XzIwMTUgPC0NCiAgcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiLi4vZGF0YS9TcHJpbmcgMjAxNC0yMDE1IEFIUlAgU2FsbW9uIEJpb2xvZ2ljYWwgRGF0YSAyMDIyMDMyMl8xMjI1MzguY3N2IikNCg0KKG9jZWFuYWtfb2cgPC0gZHBseXI6OmJpbmRfcm93cyhlcmJfMjAxNywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9ja2RhbGVfMjAxNV8yMDE2X2hvZ2FuXzIwMTVfMjAxNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbmdfMjAxNF8yMDE1KQ0KKQ0KYGBgDQoNCkNvbmZpcm0gdGhlIGFic2VuY2Ugb2YgbGVuZ3RoIGRhdGEgZm9yIFBTUFJJTjE0XzE3NQ0KYGBge3J9DQpzcHJpbmdfMjAxNF8yMDE1ICU+JSANCiAgZHBseXI6OmZpbHRlcihTSUxMWV9DT0RFID09ICJQU1BSSU4xNCIsDQogICAgICAgICAgICAgICAgRklTSF9JRCAlaW4lIDE3MjoxNzgsDQogICAgICAgICAgICAgICAgVElTU1VFX1RZUEUgPT0gIkhlYXJ0LWJ1bGJ1cyBhcnRlcmlvc3VzIikNCmBgYA0KDQpSZWZvcm1hdA0KYGBge3J9DQooDQogIG9jZWFuYWsgPC0gb2NlYW5ha19vZyAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKFRJU1NVRV9UWVBFID09ICJIZWFydC1idWxidXMgYXJ0ZXJpb3N1cyIpICU+JQ0KICAgIGRwbHlyOjpyZW5hbWUoDQogICAgICBzaWxseSA9IFNJTExZX0NPREUsDQogICAgICBmaXNoX2lkID0gRklTSF9JRCwNCiAgICAgIHRpc3N1ZV90eXBlID0gVElTU1VFX1RZUEUsDQogICAgICBkd3BfYmFyY29kZSA9IEROQV9UUkFZX0NPREUsDQogICAgICBkd3Bfd2VsbCA9IEROQV9UUkFZX1dFTExfQ09ERSwNCiAgICAgIHNhbXBsZV9kYXRlID0gU0FNUExFX0RBVEUsDQogICAgICBzZXggPSBTRVgsDQogICAgICBsZW5ndGhfbW1fbWVoID0gTEVOR1RIX01NLA0KICAgICAgb3RvbGl0aF9tYXJrX3ByZXNlbnQgPSBPVE9MSVRIX01BUktfUFJFU0VOVCwNCiAgICAgIG90b2xpdGhfbWFya19pZCA9IE9UT0xJVEhfTUFSS19JRA0KICAgICkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHNhbXBsZV9kYXRlID0gbHVicmlkYXRlOjp5bWQoc2FtcGxlX2RhdGUpLA0KICAgICAgaGF0Y2hlcnkgPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgICAhaXMubmEob3RvbGl0aF9tYXJrX2lkKSB+IHN0cmluZ3I6OnN0cl9zdWIoDQogICAgICAgICAgc3RyaW5nID0gb3RvbGl0aF9tYXJrX2lkLA0KICAgICAgICAgIHN0YXJ0ID0gMSwNCiAgICAgICAgICBlbmQgPSAzDQogICAgICAgICksDQogICAgICAgIFRSVUUgfiBvdG9saXRoX21hcmtfaWQNCiAgICAgICksDQogICAgICBvcmlnaW4gPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgICBvdG9saXRoX21hcmtfcHJlc2VudCA9PSAiTk8iIH4gIm5hdHVyYWwiLA0KICAgICAgICBvdG9saXRoX21hcmtfcHJlc2VudCA9PSAiWUVTIiB+ICJoYXRjaGVyeSINCiAgICAgICksDQogICAgICBzZXggPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgICBzZXggPT0gIk0iIH4gIm1hbGUiLA0KICAgICAgICBzZXggPT0gIkYiIH4gImZlbWFsZSIsDQogICAgICAgIHNleCA9PSAiVSIgfiAidW5rbm93biIsDQogICAgICAgIFRSVUUgfiBzZXgNCiAgICAgICkNCiAgICApICU+JQ0KICAgIHRpZHlyOjp1bml0ZSgNCiAgICAgIGNvbCA9ICJzaWxseV9zb3VyY2UiLA0KICAgICAgYyhzaWxseSwgZmlzaF9pZCksDQogICAgICBzZXAgPSAiXyIsDQogICAgICByZW1vdmUgPSBGQUxTRQ0KICAgICkgJT4lDQogICAgdGlkeXI6OnVuaXRlKA0KICAgICAgY29sID0gInNhbXBsZSIsDQogICAgICBjKGR3cF9iYXJjb2RlLCBkd3Bfd2VsbCksDQogICAgICBzZXAgPSAiXyIsDQogICAgICByZW1vdmUgPSBGQUxTRQ0KICAgICkgJT4lDQogICAgZHBseXI6OnNlbGVjdCgNCiAgICAgIHNpbGx5X3NvdXJjZSwNCiAgICAgIHNhbXBsZSwNCiAgICAgIHNpbGx5LA0KICAgICAgZmlzaF9pZCwNCiAgICAgIGR3cF9iYXJjb2RlLA0KICAgICAgZHdwX3dlbGwsDQogICAgICBzYW1wbGVfZGF0ZSwNCiAgICAgIHNleCwNCiAgICAgIGxlbmd0aF9tbV9tZWgsDQogICAgICBvcmlnaW4sDQogICAgICBvdG9saXRoX21hcmtfcHJlc2VudCwNCiAgICAgIG90b2xpdGhfbWFya19pZCwNCiAgICAgIGhhdGNoZXJ5DQogICAgKQ0KKQ0KYGBgDQoNCiMjIEpvaW4NCg0KSm9pbiBpbiBsb2NhdGlvbiBkYXRhIHRvIHRoZSBldmVyeXRoaW5nIGVsc2UgZnJvbSB0aGUgZGF0YSB3YXJlaG91c2UuDQpgYGB7cn0NCihwYWlyZWRfZGF0YSA8LSBvY2VhbmFrICU+JQ0KICAgZHBseXI6OmxlZnRfam9pbih5ID0gbG9jYXRpb25fdGlkYWwsIGJ5ID0gInNhbXBsZSIpKQ0KYGBgDQoNCk5vdyBqb2luIHRoaXMgYWxsIGluIHdpdGggdGhlIGB3ZWxsc19yZXZpc2VkX3YyYA0KYGBge3J9DQp3ZWxsc19yZXZpc2VkX3YyICU+JSANCiAgdGlkeXI6OnVuaXRlKA0KICAgICAgY29sID0gInNpbGx5X3NvdXJjZSIsDQogICAgICBjKCJTaWxseSBDb2RlIiwgIkZpc2giKSwNCiAgICAgIHNlcCA9ICJfIiwNCiAgICAgIHJlbW92ZSA9IEZBTFNFDQogICAgKSAlPiUNCiAgZHBseXI6OmxlZnRfam9pbih5ID0gcGFpcmVkX2RhdGEsIGJ5ID0gInNpbGx5X3NvdXJjZSIpICU+JSANCiAgZHBseXI6OmZpbHRlcighaXMubmEoc2FtcGxlKSkNCmBgYA0KDQpEb3VibGUgY2hlY2sgdG8gbWFrZSBzdXJlIHRoaXMgaXMgaG93IG1hbnkgZmlzaCB3ZSBzaG91bGQgaGF2ZS4uLg0KYGBge3J9DQp3ZWxsc19yZXZpc2VkX3YyICU+JSANCiAgZHBseXI6OmZpbHRlcihgU2lsbHkgQ29kZWAgJWluJSBjKCJQRVJCMTciLCAiUEhPR0FOMTUiLCAiUEhPR0FOMTYiLCAiUFNQUklOMTQiLCAiUFNQUklOMTUiLCAiUFNUT0NLMTUiLCAiUFNUT0NLMTYiKSkgJT4lIA0KICBkcGx5cjo6Y291bnQoYFNpbGx5IENvZGVgKQ0KYGBgDQoNCldoZXcsIHdlIGRpZCBpdA0KDQojIFJlYWQgaW4gYGV4dHJhY3Rpb25fc2VsZWN0aW9uLnhsc3hgIHRhYiBpbmRpdmlkdWFscw0KDQpgYGB7cn0NCigNCiAgaW5kaXZpZHVhbHMgPC0NCiAgICByZWFkeGw6OnJlYWRfeGxzeChwYXRoID0gIi4uL291dHB1dC9leHRyYWN0aW9uX3NlbGVjdGlvbl9yZXZpc2VkXzIwMjIxMDE0Lnhsc3giLCBzaGVldCA9ICJpbmRpdmlkdWFscyIpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3Qoc2lsbHksIGZpc2hfaWQsIHNleCwgb3JpZ2luLCBkYXRlLCBjb21tZW50KSAlPiUgDQogICAgZHBseXI6Om11dGF0ZShkYXRlID0gbHVicmlkYXRlOjphc19kYXRlKGRhdGUpKQ0KKQ0KYGBgDQoNClN0b3BwZWQgaGVyZSwgbmVlZCB0byBmaXggdGhpcyAxMS8xNS8yMiEgYHBhaXJlZF9kYXRhYCBpcyBOT1Qgam9pbmluZywgZm9yIHdoYXRldmVyIGVzb3RlcmljIHJlYXNvbi4NCg0KV2UgYXJlIGdvaW5nIHRvIHJlcGxhY2UgdGhpcyB0YWIgd2l0aCBhIGpvaW4gYmV0d2VlbiBgd2VsbHNfcmV2aXNlZGAsIHRoZSBleGlzdGluZyBgaW5kaXZpZHVhbHNgIHRhYiwgYW5kIG91ciBuZXcgYHBhaXJlZCBkYXRhYA0KYGBge3J9DQooDQogIGluZGl2aWR1YWxzX25ldyA8LSB3ZWxsc19yZXZpc2VkX3YyICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoLWBMYWIgUHJvamVjdCBJRGApICU+JQ0KICAgIGRwbHlyOjpyZW5hbWUoDQogICAgICBkbmFfcGxhdGVfaWQgPSAiUGxhdGUgSUQiLA0KICAgICAgc2lsbHkgPSAiU2lsbHkgQ29kZSIsDQogICAgICBmaXNoX2lkID0gIkZpc2giLA0KICAgICAgZG5hX3BsYXRlX3dlbGwgPSAiV2VsbCIsDQogICAgICB0aXNzdWVfdHlwZSA9ICJUaXNzdWUgVHlwZSINCiAgICApICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoZG5hX3BsYXRlX2lkLA0KICAgICAgICAgICAgICAgICAgZG5hX3BsYXRlX3dlbGwsDQogICAgICAgICAgICAgICAgICBzaWxseSwNCiAgICAgICAgICAgICAgICAgIGZpc2hfaWQsDQogICAgICAgICAgICAgICAgICB0aXNzdWVfdHlwZSkgJT4lDQogICAgdGlkeXI6OnVuaXRlKA0KICAgICAgY29sID0gInNpbGx5X3NvdXJjZSIsDQogICAgICBjKCJzaWxseSIsICJmaXNoX2lkIiksDQogICAgICBzZXAgPSAiXyIsDQogICAgICByZW1vdmUgPSBGQUxTRQ0KICAgICkgJT4lDQogICAgZHBseXI6OmxlZnRfam9pbih5ID0gaW5kaXZpZHVhbHMsIGJ5ID0gYygic2lsbHkiLCAiZmlzaF9pZCIpKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKA0KICAgICAgeSA9IHBhaXJlZF9kYXRhLA0KICAgICAgYnkgPSAic2lsbHlfc291cmNlIiwNCiAgICAgIHN1ZmZpeCA9IGMoIl9pbmRpdiIsICJfcGFpcmVkIikNCiAgICApDQopDQpgYGANCg0KRG91YmxlIGNoZWNrIG91ciBob21taWUgaW4gNjMyMThfQTcNCmBgYHtyfQ0KaW5kaXZpZHVhbHNfbmV3ICU+JSANCiAgZHBseXI6OmZpbHRlcihkbmFfcGxhdGVfaWQgPT0gNjMyMTgpDQpgYGANCg0KR3JlYXQsIHdyaXRlIGFsbCBvZiB0aGlzIG91dCwgcGFzdGUgaW50byBgZXh0cmFjdGlvbl9zZWxlY3Rpb25fcmV2aXNlZF8yMDIyMTExNS54bHN4YCBhcyB0aGUgbmV3IGBpbmRpdmlkdWFscyB0YWJgLCBhbm5vdGF0ZSB0aGUgY29sdW1ucywgc2VuZCB0byBXaWxsLg0KDQpgYGB7cn0NCnJlYWRyOjp3cml0ZV9jc3YoeCA9IGluZGl2aWR1YWxzX25ldywgZmlsZSA9ICIuLi9vdXRwdXQvZXh0cmFjdGlvbl9zZWxlY3Rpb25fcmV2aXNlZF8yMDIyMTExNS5jc3YiKQ0KYGBgDQoNCkVuZC4uLnRpbWUgZm9yIGEgYmVlcg==